package com.sky.utils;

import com.sky.properties.WeChatProperties;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.PrivateKey;

/**
 * 微信支付回调签名验证器
 * 用于验证微信支付回调请求的签名真实性
 */
@Component
@Slf4j
public class WxPayCallbackVerifier {
    @Autowired
    private WeChatProperties weChatPayProperties;

    // 签名验证器（全局单例）
    private Verifier verifier;

    /**
     * 初始化验证器（项目启动时执行）
     */
    @PostConstruct
    public void init() {
        try {
            // 1. 加载商户私钥（用于向微信支付平台获取平台证书）
            PrivateKey privateKey = PemUtil.loadPrivateKey(
                    new FileInputStream(weChatPayProperties.getPrivateKeyFilePath())
            );

            // 2. 初始化证书管理器（用于获取微信支付平台证书）
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器注册商户信息
            certificatesManager.putMerchant(
                    weChatPayProperties.getMchid(),
                    new WechatPay2Credentials(
                            weChatPayProperties.getMchid(),
                            new PrivateKeySigner(
                                    weChatPayProperties.getMchSerialNo(),
                                    privateKey
                            )
                    ),
                    weChatPayProperties.getApiV3Key().getBytes()
            );

            // 3. 获取签名验证器（基于微信支付平台证书）
            verifier = certificatesManager.getVerifier(weChatPayProperties.getMchid());
            log.info("微信支付签名验证器初始化成功");
        } catch (FileNotFoundException e) {
            log.error("加载商户私钥失败，路径错误: {}", weChatPayProperties.getPrivateKeyFilePath(), e);
            throw new RuntimeException("微信支付验证器初始化失败", e);
        } catch (HttpCodeException e) {
            log.error("获取微信支付平台证书失败，HTTP状态码: {}", e.hashCode(), e);
            throw new RuntimeException("微信支付验证器初始化失败", e);
        } catch (NotFoundException e) {
            log.error("商户信息未注册到证书管理器", e);
            throw new RuntimeException("微信支付验证器初始化失败", e);
        } catch (Exception e) {
            log.error("微信支付签名验证器初始化异常", e);
            throw new RuntimeException("微信支付验证器初始化失败", e);
        }
    }

    /**
     * 验证签名
     *
     * @param serial     微信支付证书序列号（从请求头 Wechatpay-Serial 获取）
     * @param message    待验签的字符串（格式：timestamp\nnonce\nbody\n）
     * @param signature  微信支付签名（从请求头 Wechatpay-Signature 获取）
     * @return 签名是否有效
     */
    public boolean verify(String serial, byte[] message, String signature) {
        try {
            return verifier.verify(serial, message, signature);
        } catch (Exception e) {
            log.error("签名验证失败: serial={}, signature={}", serial, signature, e);
            return false;
        }
    }
}
